
package com.facetest.activity;

import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Size;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.fragment.app.FragmentActivity;

import com.facetest.R;
import com.facetest.currencyview.LegacyCameraConnectionFragment;
import com.facetest.engine.CheckFaceEngine;
import com.seeta.sdk.util.SeetaHelper;
import com.facetest.utils.MyLogger;
import com.facetest.utils.NV21ToBitmap;
import com.facetest.utils.PermissionUtils;
import com.facetest.utils.SensorEventUtil;
import com.tenginekit.AndroidConfig;
import com.tenginekit.Face;

public abstract class CameraActivity extends FragmentActivity implements
        Camera.PreviewCallback{
    private static final String TAG = "CameraActicity";

    // 照相机预览宽
    public int previewWidth = 0;
    // 照相机预览高
    public int previewHeight = 0;
    // 展示区域宽
    public static float ScreenWidth;
    // 展示区域高
    public static float ScreenHeight;

    public static int CameraId = 0;

    private boolean isProcessingFrame = false;
    // 是否是前置摄像头
    public static boolean is_front_camera = true;

    private Handler handler;
    private HandlerThread handlerThread;
    protected SensorEventUtil sensorEventUtil;

    // 相机的数据 nv21格式
    protected byte[] mNV21Bytes;

    private Runnable postInferenceCallback;
    private Runnable imageConverter;
    public TextView msg,rest,action;
    public ImageView photo;
    public NV21ToBitmap nv21ToBitmap;
    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(null);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        setContentView(R.layout.activity_camera);
        toCheckPermission();
    }
    private void toCheckPermission(){
        PermissionUtils.checkPermission(this, new Runnable() {
            @Override
            public void run() {
                init();
            }
        });
    }
    @Override
    public void onRequestPermissionsResult(final int requestCode, final String[] permissions, final int[] grantResults) {
        if (requestCode == 1) {
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED
                    && grantResults[1] == PackageManager.PERMISSION_GRANTED) {
                init();
            } else {
                toCheckPermission();
            }
        }
    }
    private void init(){
        msg = findViewById(R.id.msg);
        photo = findViewById(R.id.photo);
        rest = findViewById(R.id.rest);
        action = findViewById(R.id.action);
        //动作识别监测
        CheckFaceEngine.getInstance().setOnFaceCheckResult(new CheckFaceEngine.OnFaceCheckResult() {
            @Override
            public void onAction(int type) {
                switch (type){
                    case CheckFaceEngine.ACTION_TYPE_EYE:
                        action.setText("识别到的动作:眨眼");
                        break;
                    case CheckFaceEngine.ACTION_TYPE_MOUTH:
                        action.setText("识别到的动作:张嘴");
                        break;
                    case CheckFaceEngine.ACTION_TYPE_LEFT_RIGHT_HEAD:
                        action.setText("识别到的动作:左右摇头");
                        break;
                    case CheckFaceEngine.ACTION_TYPE_RISE_HEAD:
                        action.setText("识别到的动作:抬头");
                        break;
                    case CheckFaceEngine.ACTION_TYPE_BOW_HEAD:
                        action.setText("识别到的动作:低头");
                        break;
                    case CheckFaceEngine.ACTION_TYPE_NOT_ZHENGDUI:
                        action.setText("请正对屏幕!");
                        break;
                    default:
                        action.setText("未识别到任何动作");
                        break;
                }
            }
        });
        nv21ToBitmap = new NV21ToBitmap(CameraActivity.this);
        setFragment();
        initView();
        new Thread(new Runnable() {
            @Override
            public void run() {
                if (SeetaHelper.copyAts(CameraActivity.this)) {
                    SeetaHelper.getInstance().init();
                }
            }
        }).start();
    }



    public void Init() {
        mNV21Bytes = new byte[previewHeight * previewWidth];

        /**
         * 初始化
         * */
        Face.init(
                CameraActivity.this,
                AndroidConfig
                        .create()
                        .setCameraMode()
                        .setDefaultFunc().openFunc(AndroidConfig.Func.Attribution)
                        .setDefaultInputImageFormat()
                        .setInputImageSize(previewWidth, previewHeight)
                        .setOutputImageSize((int) ScreenWidth, (int) ScreenHeight)
        );
        if (sensorEventUtil == null) {
            sensorEventUtil = new SensorEventUtil(this);
        }
    }

    /**
     * Callback for android.hardware.Camera API
     */
    @SuppressLint("NewApi")
    @Override
    public void onPreviewFrame(final byte[] bytes, final Camera camera) {
        if (isProcessingFrame) {
            return;
        }
        isProcessingFrame = true;
        try {
            if (mNV21Bytes == null) {
                Camera.Size previewSize = camera.getParameters().getPreviewSize();
                previewHeight = previewSize.height;
                previewWidth = previewSize.width;
                Init();
                onPreviewSizeChosen(new Size(previewSize.width, previewSize.height));
            }
        } catch (final Exception e) {
            MyLogger.logError(TAG, "onPreviewFrame: " + e);
            return;
        }
        imageConverter = new Runnable() {
            @Override
            public void run() {
                mNV21Bytes = bytes;
            }
        };
        postInferenceCallback = new Runnable() {
            @Override
            public void run() {
                camera.addCallbackBuffer(bytes);
                isProcessingFrame = false;
            }
        };
        processImage();
    }

    @Override
    public synchronized void onStart() {
        super.onStart();
    }

    @Override
    public synchronized void onResume() {
        super.onResume();
        handlerThread = new HandlerThread("inference");
        handlerThread.start();
        handler = new Handler(handlerThread.getLooper());
        processImage();
    }

    @Override
    public synchronized void onPause() {
        handlerThread.quitSafely();
        try {
            handlerThread.join();
            handlerThread = null;
            handler = null;
        } catch (final InterruptedException e) {
            MyLogger.logError(TAG, "onPause: " + e);
        }
        super.onPause();
    }

    @Override
    public synchronized void onStop() {
        super.onStop();
    }

    @Override
    public synchronized void onDestroy() {
        super.onDestroy();
        /**
         * 释放
         * */
        Face.release();
    }


    protected void setFragment() {
        LegacyCameraConnectionFragment fragment = new LegacyCameraConnectionFragment(this, getLayoutId(), getDesiredPreviewFrameSize());
        CameraId = fragment.getCameraId();
        getFragmentManager().beginTransaction().replace(R.id.container, fragment).commit();
    }

    protected void readyForNextImage() {
        if (postInferenceCallback != null) {
            postInferenceCallback.run();
        }
    }

    protected synchronized void runInBackground(final Runnable r) {
        if (handler != null) {
            handler.post(r);
        }
    }

    protected abstract void initView();
    protected abstract void processImage();

    protected abstract void onPreviewSizeChosen(final Size size);

    protected abstract int getLayoutId();

    protected abstract Size getDesiredPreviewFrameSize();

    //得到最新的bytes
    protected void getCameraBytes() {
        if (imageConverter != null) {
            imageConverter.run();
        }
    }

}
